package com.itfreer.xjmh.configuration;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import com.itfreer.sso.authentication.AuthenticationTransactionManager;
import com.itfreer.sso.authentication.PrincipalElectionStrategy;
import com.itfreer.sso.authentication.handler.AuthenticationHandler;
import com.itfreer.sso.authentication.policy.AuthenticationPolicy;
import com.itfreer.sso.authentication.policy.AuthenticationPolicyFactory;
import com.itfreer.sso.authentication.populator.AuthenticationMetaDataPopulator;
import com.itfreer.sso.authentication.principal.PrincipalAttributes;
import com.itfreer.sso.authentication.principal.PrincipalFactory;
import com.itfreer.sso.authentication.principal.PrincipalResolver;
import com.itfreer.sso.base.authentication.DefaultAuthenticationTransactionManager;
import com.itfreer.sso.base.authentication.DefaultPrincipalElectionStrategy;
import com.itfreer.sso.base.authentication.QueryDatabaseAuthenticationHandler;
import com.itfreer.sso.base.authentication.QueryDatabasePrincipalAttributes;
import com.itfreer.sso.base.authentication.handler.AcceptUsersAuthenticationHandler;
import com.itfreer.sso.base.authentication.handler.DefaultPasswordEncoder;
import com.itfreer.sso.base.authentication.policy.AcceptAnyAuthenticationPolicyFactory;
import com.itfreer.sso.base.authentication.policy.AnyAuthenticationPolicy;
import com.itfreer.sso.base.authentication.populator.RememberMeAuthenticationMetaDataPopulator;
import com.itfreer.sso.base.authentication.populator.SuccessfulHandlerMetaDataPopulator;
import com.itfreer.sso.base.authentication.principal.DefaultPrincipalFactory;
import com.itfreer.sso.base.authentication.principal.DefaultPrincipalResolver;
import com.itfreer.sso.base.services.JsonServiceRegistryDao;
import com.itfreer.sso.base.services.MemoryServicesManagerCache;
import com.itfreer.sso.base.services.WebApplicationServiceFactory;
import com.itfreer.sso.base.tickets.HostNameBasedUniqueTicketIdGenerator.ServiceTicketIdGenerator;
import com.itfreer.sso.base.tickets.registry.AbstractTicketRegistry;
import com.itfreer.sso.base.tickets.registry.DefaultTicketRegistry;
import com.itfreer.sso.base.tickets.support.AbstractExpirationPolicy;
import com.itfreer.sso.base.tickets.support.MultiTimeUseOrTimeoutExpirationPolicy;
import com.itfreer.sso.base.tickets.support.TicketGrantingTicketExpirationPolicy;
import com.itfreer.sso.base.web.AbstractArgumentExtractor;
import com.itfreer.sso.base.web.DefaultArgumentExtractor;
import com.itfreer.sso.services.ServiceFactory;
import com.itfreer.sso.services.ServiceRegistryDao;
import com.itfreer.sso.services.ServicesManagerCache;

/**
 * 单点登录服务端配置
 */
@Configuration
public class SsoServiceConfiguration {

	/**
	 * 服务工厂列表，用于从request创建Service对象
	 *
	 * @return
	 */
	@Bean(name = "serviceFactoryList")
	public List<ServiceFactory<?>> serviceFactoryList(@Qualifier("webApplicationServiceFactory") WebApplicationServiceFactory webAppFactory) {
		List<ServiceFactory<?>> list = new ArrayList<>();
		list.add(webAppFactory);
		return list;
	}

	/**
	 * request参数解释器列表，用于调用ServiceFactory从request创建Service对象
	 *
	 * @param e
	 * @return
	 */
	@Bean(name = "argumentExtractors")
	public List<AbstractArgumentExtractor> argumentExtractors(@Qualifier("defaultArgumentExtractor") DefaultArgumentExtractor e) {
		List<AbstractArgumentExtractor> list = new ArrayList<>();
		list.add(e);
		return list;
	}

	/**
	 * 唯一值构建
	 *
	 * @param e
	 * @return
	 */
	@Bean(name = "uniqueIdGeneratorsMap")
	public Map<String, Object> uniqueIdGeneratorsMap(@Qualifier("serviceTicketUniqueIdGenerator") ServiceTicketIdGenerator e) {
		Map<String, Object> map = new HashMap<>();
		map.put("com.itfreer.sso.base.services.authentication.SimpleWebApplicationServiceImpl", e);
		return map;
	}

	/**
	 * 认证元数据填充处理器
	 *
	 * @param e
	 * @param r
	 * @return
	 */
	@Bean(name = "authenticationMetadataPopulators")
	public List<AuthenticationMetaDataPopulator> authenticationMetadataPopulators(
			@Qualifier("successfulHandlerMetaDataPopulator") SuccessfulHandlerMetaDataPopulator e,
			@Qualifier("rememberMeAuthenticationMetaDataPopulator") RememberMeAuthenticationMetaDataPopulator r) {
		List<AuthenticationMetaDataPopulator> list = new ArrayList<>();
		list.add(e);
		list.add(r);
		return list;
	}

	/**
	 * 认证器列表
	 *
	 * @return
	 */
	@Bean(name = "authenticationHandlersResolvers")
	public Map<AuthenticationHandler, PrincipalResolver> authenticationHandlersResolvers(
			@Qualifier("queryDatabaseAuthenticationHandler") QueryDatabaseAuthenticationHandler dbHandler,
			@Qualifier("acceptUsersAuthenticationHandler") AcceptUsersAuthenticationHandler a,
			@Qualifier("defaultPrincipalResolver") DefaultPrincipalResolver c) {
		DefaultPasswordEncoder encoder = new DefaultPasswordEncoder("SHA1");
		encoder.setCharacterEncoding("UTF-8");
		dbHandler.setSql("select s_password from sso_user_uthentication where is_valid=1 and s_accounts=?");
		dbHandler.setPasswordEncoder(encoder);

		Map<AuthenticationHandler, PrincipalResolver> map = new HashMap<>();
		map.put(a, c);
		map.put(dbHandler, c);
		return map;
	}

	/**
	 * 票据属性解释器
	 *
	 * @return
	 */
	@Bean(name = "principalAttributes")
	public PrincipalAttributes principalAttributes() {
		QueryDatabasePrincipalAttributes attributes = new QueryDatabasePrincipalAttributes();
		attributes.setSql("select id as user_id from sso_user_uthentication where s_accounts=?");
		return attributes;
	}

	/**
	 * 服务注册器
	 *
	 * @param a
	 * @return
	 */
	@Bean(name = "serviceRegistryDao")
	public ServiceRegistryDao serviceRegistryDao(@Qualifier("jsonServiceRegistryDao") JsonServiceRegistryDao a) {
		return a;
	}

	/**
	 * 服务注册缓存
	 *
	 * @param a
	 * @return
	 */
	@Bean(name = "servicesManagerCache")
	public ServicesManagerCache servicesManagerCache(@Qualifier("memoryServicesManagerCache") MemoryServicesManagerCache a) {
		return a;
	}

	/**
	 * 票据注册
	 *
	 * @param a
	 * @return
	 */
	@Bean(name = "ticketRegistry")
	public AbstractTicketRegistry ticketRegistry(@Qualifier("defaultTicketRegistry") DefaultTicketRegistry a) {
		return a;
	}

	/**
	 * 票据过期
	 */
	@Bean(name = "grantingTicketExpirationPolicy")
	public AbstractExpirationPolicy grantingTicketExpirationPolicy(@Qualifier("ticketGrantingTicketExpirationPolicy") TicketGrantingTicketExpirationPolicy a) {
		return a;
	}

	@Bean(name = "serviceTicketExpirationPolicy")
	public AbstractExpirationPolicy serviceTicketExpirationPolicy(@Qualifier("multiTimeUseOrTimeoutExpirationPolicy") MultiTimeUseOrTimeoutExpirationPolicy a) {
		return a;
	}

	/**
	 * 认证成功策略
	 */
	@Bean(name = "authenticationPolicy")
	public AuthenticationPolicy<?> authenticationPolicy(@Qualifier("anyAuthenticationPolicy") AnyAuthenticationPolicy a) {
		return a;
	}

	@Bean(name = "authenticationPolicyFactory")
	public AuthenticationPolicyFactory<?> authenticationPolicyFactory(@Qualifier("acceptAnyAuthenticationPolicyFactory") AcceptAnyAuthenticationPolicyFactory a) {
		return a;
	}

	@Bean(name = "principalFactory")
	public PrincipalFactory principalFactory(@Qualifier("defaultPrincipalFactory") DefaultPrincipalFactory a) {
		return a;
	}

	@Bean(name = "authenticationTransactionManager")
	public AuthenticationTransactionManager authenticationTransactionManager(
			@Qualifier("defaultAuthenticationTransactionManager") DefaultAuthenticationTransactionManager a) {
		return a;
	}

	@Bean(name = "principalElectionStrategy")
	public PrincipalElectionStrategy principalElectionStrategy(@Qualifier("defaultPrincipalElectionStrategy") DefaultPrincipalElectionStrategy a) {
		return a;
	}

	/**
	 * 服务票据定时器
	 *
	 * @return
	 */
	@Bean(name = "scheduler")
	public SchedulerFactoryBean schedulerFactory() {
		SchedulerFactoryBean bean = new SchedulerFactoryBean();
		// 用于quartz集群,QuartzScheduler 启动时更新己存在的Job
		bean.setOverwriteExistingJobs(true);
		// 延时启动，应用启动1秒后
		bean.setStartupDelay(1);
		return bean;
	}
}